<script setup>
import { ref, onBeforeUnmount, watch, computed } from "vue";
import { useI18n } from "vue-i18n";
import {
  Hash,
  Clock,
  Trophy,
  Star,
  CheckCircle,
  XCircle,
} from "lucide-vue-next";

const { t } = useI18n();
const emit = defineEmits(["complete"]);

const stage = ref("instructions");
const currentLevel = ref(1); // 从1-back开始
const currentTrialIndex = ref(0);
const trials = ref([]);
const responses = ref([]);
const reactionTimes = ref([]);
const timeLeft = ref(480); // 8分钟
const startTime = ref(0);
const trialStartTime = ref(0);
const currentDigit = ref(null);
const showDigit = ref(false);
const score = ref(0);
const levelScores = ref([]);
const showFeedback = ref(false);
const feedbackCorrect = ref(false);

const TRIALS_PER_LEVEL = 20;
const MAX_LEVEL = 5;
const DIGIT_DISPLAY_TIME = 500; // 数字显示时间

let timerInterval;
let trialTimeout;

const generateTrials = (nLevel) => {
  const newTrials = [];
  const digits = [1, 2, 3, 4, 5, 6, 7, 8, 9];
  const sequence = [];
  for (let i = 0; i < TRIALS_PER_LEVEL; i++) {
    sequence.push(digits[Math.floor(Math.random() * digits.length)]);
  }

  const matchCount = Math.floor(TRIALS_PER_LEVEL * 0.3);
  const matchPositions = new Set();

  while (matchPositions.size < matchCount) {
    const pos =
      Math.floor(Math.random() * (TRIALS_PER_LEVEL - nLevel)) + nLevel;
    matchPositions.add(pos);
  }

  matchPositions.forEach((pos) => {
    sequence[pos] = sequence[pos - nLevel];
  });

  for (let i = 0; i < TRIALS_PER_LEVEL; i++) {
    const isMatch = i >= nLevel && sequence[i] === sequence[i - nLevel];
    newTrials.push({ id: i, digit: sequence[i], isMatch, nLevel });
  }
  return newTrials;
};

const startTrial = () => {
  if (currentTrialIndex.value >= trials.value.length) return;
  const trial = trials.value[currentTrialIndex.value];
  if (!trial) return;

  currentDigit.value = trial.digit;
  showDigit.value = true;
  trialStartTime.value = Date.now();

  trialTimeout = setTimeout(() => {
    showDigit.value = false;
  }, DIGIT_DISPLAY_TIME);
};

const handleStartTest = () => {
  stage.value = "test";
  startTime.value = Date.now();
};

const handleResponse = (userResponse) => {
  const trial = trials.value[currentTrialIndex.value];
  if (!trial) return;

  const reactionTime = Date.now() - trialStartTime.value;
  const correct = userResponse === trial.isMatch;

  responses.value.push(userResponse);
  reactionTimes.value.push(reactionTime);

  if (correct) {
    score.value++;
  }

  feedbackCorrect.value = correct;
  showFeedback.value = true;

  setTimeout(() => {
    showFeedback.value = false;
    if (currentTrialIndex.value < trials.value.length - 1) {
      currentTrialIndex.value++;
      setTimeout(startTrial, 500);
    } else {
      finishLevel();
    }
  }, 800);
};

const finishLevel = () => {
  const levelTrials = trials.value;
  const levelCorrect = responses.value
    .slice(-levelTrials.length)
    .filter(
      (response, index) => response === levelTrials[index].isMatch
    ).length;
  const levelAccuracy = levelCorrect / levelTrials.length;

  levelScores.value.push(levelAccuracy);

  if (levelAccuracy >= 0.75 && currentLevel.value < MAX_LEVEL) {
    currentLevel.value++;
    currentTrialIndex.value = 0;
    responses.value = [];
    reactionTimes.value = [];
    trials.value = generateTrials(currentLevel.value);
    startTrial();
  } else {
    stage.value = "results";
  }
};

const handleComplete = () => {
  const totalTrials = responses.value.length;
  const totalCorrect = score.value;
  const overallAccuracy =
    totalTrials > 0 ? Math.round((totalCorrect / totalTrials) * 100) : 0;
  const workingMemorySpan =
    levelScores.value.findIndex((s) => s < 0.75) + 1 ||
    levelScores.value.length ||
    1;
  const finalScore = Math.min(
    100,
    Math.round(overallAccuracy + (workingMemorySpan - 1) * 10)
  );
  const averageReactionTime =
    reactionTimes.value.length > 0
      ? Math.round(
          reactionTimes.value.reduce((a, b) => a + b, 0) /
            reactionTimes.value.length
        )
      : 0;
  const timeUsed = Math.round((Date.now() - startTime.value) / 1000);

  const result = {
    id: Date.now().toString(),
    testType: "digit-memory",
    score: finalScore,
    completedAt: new Date(),
    duration: timeUsed,
    details: {
      totalTrials,
      totalCorrect,
      overallAccuracy,
      maxLevelReached: currentLevel.value,
      workingMemorySpan,
      averageReactionTime,
      levelPerformance: levelScores.value.map((acc, i) => ({
        level: i + 1,
        accuracy: Math.round(acc * 100),
        trials: TRIALS_PER_LEVEL,
      })),
      nBackCapacity: workingMemorySpan,
      totalScore: score.value,
    },
  };
  emit("complete", result);
};

watch([stage, currentLevel], ([newStage, newLevel]) => {
  if (newStage === "test") {
    trials.value = generateTrials(newLevel);
    currentTrialIndex.value = 0;
    startTrial();
  }
});

watch(stage, (newStage) => {
  if (newStage === "test" && timeLeft.value > 0) {
    timerInterval = setInterval(() => {
      timeLeft.value--;
      if (timeLeft.value <= 0) {
        clearInterval(timerInterval);
        stage.value = "results";
      }
    }, 1000);
  } else {
    clearInterval(timerInterval);
  }
});

onBeforeUnmount(() => {
  clearInterval(timerInterval);
  clearTimeout(trialTimeout);
});

const progress = computed(
  () =>
    (((currentLevel.value - 1) * TRIALS_PER_LEVEL + currentTrialIndex.value) /
      (MAX_LEVEL * TRIALS_PER_LEVEL)) *
    100
);

const finalResult = computed(() => {
  const totalTrials = responses.value.length;
  const totalCorrect = score.value;
  const overallAccuracy =
    totalTrials > 0 ? Math.round((totalCorrect / totalTrials) * 100) : 0;
  const workingMemorySpan =
    levelScores.value.findIndex((s) => s < 0.75) + 1 ||
    levelScores.value.length ||
    1;
  const finalScore = Math.min(
    100,
    Math.round(overallAccuracy + (workingMemorySpan - 1) * 10)
  );
  return {
    finalScore,
    workingMemorySpan,
    overallAccuracy,
    totalCorrect,
    totalTrials,
  };
});
</script>

<template>
  <div v-if="stage === 'instructions'" class="max-w-2xl mx-auto">
    <Card class="bg-white/90 backdrop-blur-sm border-blue-200 shadow-lg">
      <CardHeader class="text-center pb-8">
        <div
          class="w-16 h-16 bg-gradient-to-br from-blue-700 to-indigo-600 rounded-2xl flex items-center justify-center mx-auto mb-4 shadow-lg"
        >
          <Hash class="w-8 h-8 text-white" />
        </div>
        <CardTitle class="text-2xl text-slate-800">
          {{ $t("digitMemoryTest.title") }}
        </CardTitle>
        <p class="text-slate-600 mt-2">
          {{ $t("digitMemoryTest.description") }}
        </p>
      </CardHeader>

      <CardContent class="space-y-6">
        <div
          class="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl p-6 border border-blue-100"
        >
          <h3 class="font-semibold text-blue-900 mb-4 flex items-center gap-2">
            <Star class="w-5 h-5" />
            {{ $t("digitMemoryTest.instructions.title") }}
          </h3>
          <div class="space-y-3 text-slate-700">
            <div class="flex gap-3">
              <span
                class="w-6 h-6 bg-blue-700 text-white rounded-full flex items-center justify-center text-sm font-semibold flex-shrink-0 mt-0.5"
                >1</span
              >
              <p>{{ $t("digitMemoryTest.instructions.step1") }}</p>
            </div>
            <div class="flex gap-3">
              <span
                class="w-6 h-6 bg-blue-700 text-white rounded-full flex items-center justify-center text-sm font-semibold flex-shrink-0 mt-0.5"
                >2</span
              >
              <p>{{ $t("digitMemoryTest.instructions.step2") }}</p>
            </div>
            <div class="flex gap-3">
              <span
                class="w-6 h-6 bg-blue-700 text-white rounded-full flex items-center justify-center text-sm font-semibold flex-shrink-0 mt-0.5"
                >3</span
              >
              <p>{{ $t("digitMemoryTest.instructions.step3") }}</p>
            </div>
            <div class="flex gap-3">
              <span
                class="w-6 h-6 bg-blue-700 text-white rounded-full flex items-center justify-center text-sm font-semibold flex-shrink-0 mt-0.5"
                >4</span
              >
              <p>{{ $t("digitMemoryTest.instructions.step4") }}</p>
            </div>
          </div>
        </div>

        <div class="bg-slate-50 rounded-xl p-4 border border-slate-200">
          <h4 class="font-semibold text-slate-700 mb-3 text-center">
            {{ $t("digitMemoryTest.example.title") }}
          </h4>
          <div class="space-y-3">
            <div class="text-center">
              <div class="text-sm text-slate-600 mb-2">
                {{ $t("digitMemoryTest.example.description") }}
              </div>
              <div class="flex justify-center gap-2 mb-2">
                <span
                  class="w-8 h-8 bg-blue-100 rounded flex items-center justify-center"
                  >5</span
                >
                <span
                  class="w-8 h-8 bg-green-100 rounded flex items-center justify-center"
                  >3</span
                >
                <span
                  class="w-8 h-8 bg-red-100 rounded flex items-center justify-center font-bold"
                  >3</span
                >
              </div>
              <div class="text-xs text-green-600">
                {{ $t("digitMemoryTest.example.match") }}
              </div>
            </div>
          </div>
        </div>

        <div class="grid md:grid-cols-3 gap-4">
          <div
            class="text-center p-4 bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl border border-blue-200"
          >
            <div class="text-2xl font-bold text-blue-700 mb-1">
              {{ MAX_LEVEL }}
            </div>
            <div class="text-sm text-blue-700">
              {{ $t("digitMemoryTest.summary.maxLevel") }}
            </div>
          </div>
          <div
            class="text-center p-4 bg-gradient-to-br from-indigo-50 to-indigo-100 rounded-xl border border-indigo-200"
          >
            <div class="text-2xl font-bold text-indigo-700 mb-1">
              {{ TRIALS_PER_LEVEL }}
            </div>
            <div class="text-sm text-indigo-700">
              {{ $t("digitMemoryTest.summary.trialsPerLevel") }}
            </div>
          </div>
          <div
            class="text-center p-4 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl border border-blue-200"
          >
            <div class="text-2xl font-bold text-slate-600 mb-1">
              {{ Math.floor(timeLeft / 60) }}
            </div>
            <div class="text-sm text-slate-700">
              {{ $t("digitMemoryTest.summary.timeLimit") }}
            </div>
          </div>
        </div>

        <Button
          class="w-full bg-gradient-to-r from-blue-700 to-indigo-600 hover:from-blue-800 hover:to-indigo-700 text-white py-3 text-lg font-semibold shadow-lg hover:shadow-xl transition-all duration-200"
          size="lg"
          @click="handleStartTest"
        >
          {{ $t("digitMemoryTest.startTest") }}
        </Button>
      </CardContent>
    </Card>
  </div>

  <div v-else-if="stage === 'test'" class="max-w-4xl mx-auto space-y-6">
    <div class="flex flex-col sm:flex-row gap-4 items-center justify-between">
      <div class="flex items-center gap-4">
        <Badge
          class="bg-blue-100 text-blue-700 border-blue-300"
          variant="outline"
        >
          {{ currentLevel }}-back
        </Badge>
        <Badge
          class="bg-indigo-100 text-indigo-700 border-indigo-300"
          variant="outline"
        >
          {{
            $t("digitMemoryTest.test.trialProgress", {
              current: currentTrialIndex + 1,
              total: TRIALS_PER_LEVEL,
            })
          }}
        </Badge>
        <div class="flex items-center gap-2 text-slate-600">
          <Trophy class="w-4 h-4" />
          <span class="font-semibold"
            >{{ score }} / {{ responses.length }}</span
          >
        </div>
      </div>

      <div class="flex items-center gap-2">
        <Clock class="w-4 h-4 text-slate-500" />
        <span
          :class="[
            'font-mono text-lg font-bold',
            timeLeft <= 60 ? 'text-red-500' : 'text-slate-700',
          ]"
        >
          {{ Math.floor(timeLeft / 60) }}:{{
            (timeLeft % 60).toString().padStart(2, "0")
          }}
        </span>
      </div>
    </div>

    <Progress :model-value="progress" class="h-2" />

    <Card class="bg-gradient-to-r from-blue-50 to-indigo-50 border-blue-200">
      <CardContent class="py-4">
        <div class="text-center">
          <h3 class="text-lg font-semibold text-blue-800">
            {{ $t("digitMemoryTest.test.question", { n: currentLevel }) }}
          </h3>
          <p
            v-if="currentTrialIndex < currentLevel"
            class="text-sm text-blue-600 mt-1"
          >
            {{ $t("digitMemoryTest.test.noJudgment", { n: currentLevel }) }}
          </p>
        </div>
      </CardContent>
    </Card>

    <Card class="bg-white/90 backdrop-blur-sm border-blue-200 shadow-lg">
      <CardContent class="py-16">
        <div class="text-center space-y-8">
          <Transition mode="out-in" name="fade">
            <div
              v-if="showDigit && currentDigit !== null"
              :key="currentDigit"
              class="w-32 h-32 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-2xl flex items-center justify-center mx-auto shadow-lg"
            >
              <span class="text-6xl font-bold text-white">
                {{ currentDigit }}
              </span>
            </div>
            <div
              v-else-if="
                !showDigit &&
                trials[currentTrialIndex] &&
                currentTrialIndex >= currentLevel
              "
              class="space-y-6"
            >
              <div class="text-xl text-slate-700 mb-6">
                {{
                  $t("digitMemoryTest.test.previousQuestion", {
                    digit: trials[currentTrialIndex].digit,
                    n: currentLevel,
                  })
                }}
              </div>
              <div class="flex justify-center gap-6">
                <Button
                  class="bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 text-white px-12 py-4 text-lg font-semibold shadow-lg"
                  size="lg"
                  @click="() => handleResponse(true)"
                >
                  <CheckCircle class="w-6 h-6 mr-2" />
                  {{ $t("digitMemoryTest.test.match") }}
                </Button>
                <Button
                  class="bg-gradient-to-r from-red-500 to-red-600 hover:from-red-600 hover:to-red-700 text-white px-12 py-4 text-lg font-semibold shadow-lg"
                  size="lg"
                  @click="() => handleResponse(false)"
                >
                  <XCircle class="w-6 h-6 mr-2" />
                  {{ $t("digitMemoryTest.test.noMatch") }}
                </Button>
              </div>
            </div>
            <div
              v-else-if="
                !showDigit &&
                trials[currentTrialIndex] &&
                currentTrialIndex < currentLevel
              "
              class="text-lg text-slate-600"
            >
              {{ $t("digitMemoryTest.test.rememberDigit") }}
            </div>
          </Transition>
        </div>
      </CardContent>
    </Card>

    <Transition name="slide-fade">
      <div
        v-if="showFeedback"
        class="fixed top-20 left-1/2 transform -translate-x-1/2 z-50"
      >
        <Card
          :class="[
            'border-0 shadow-lg',
            feedbackCorrect
              ? 'bg-green-500 text-white'
              : 'bg-red-500 text-white',
          ]"
        >
          <CardContent class="py-3 px-6">
            <div class="flex items-center gap-3">
              <CheckCircle v-if="feedbackCorrect" class="w-5 h-5" />
              <XCircle v-else class="w-5 h-5" />
              <span class="font-semibold">
                {{
                  feedbackCorrect
                    ? $t("digitMemoryTest.feedback.correct")
                    : $t("digitMemoryTest.feedback.incorrect")
                }}
              </span>
            </div>
          </CardContent>
        </Card>
      </div>
    </Transition>
  </div>

  <div v-else-if="stage === 'results'" class="max-w-2xl mx-auto">
    <Card class="bg-white/90 backdrop-blur-sm border-blue-200 shadow-xl">
      <CardHeader class="text-center pb-6">
        <div
          class="w-20 h-20 bg-gradient-to-br from-blue-700 to-indigo-600 rounded-2xl flex items-center justify-center mx-auto mb-4 shadow-lg"
        >
          <Trophy class="w-10 h-10 text-white" />
        </div>

        <CardTitle class="text-3xl text-slate-800 mb-2">{{
          $t("digitMemoryTest.results.title")
        }}</CardTitle>
        <div
          class="text-6xl font-bold bg-gradient-to-r from-blue-700 to-indigo-600 bg-clip-text text-transparent"
        >
          {{ finalResult.finalScore }}
        </div>
        <p class="text-slate-600">
          {{ $t("digitMemoryTest.results.scoreTitle") }}
        </p>
      </CardHeader>

      <CardContent class="space-y-6">
        <div class="grid grid-cols-2 gap-4">
          <div
            class="text-center p-4 bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl border border-blue-200"
          >
            <div class="text-2xl font-bold text-blue-700 mb-1">
              {{ finalResult.workingMemorySpan }}
            </div>
            <div class="text-sm text-blue-700">
              {{ $t("digitMemoryTest.results.memorySpan") }}
            </div>
          </div>
          <div
            class="text-center p-4 bg-gradient-to-br from-indigo-50 to-indigo-100 rounded-xl border border-indigo-200"
          >
            <div class="text-2xl font-bold text-indigo-700 mb-1">
              {{ finalResult.overallAccuracy }}%
            </div>
            <div class="text-sm text-indigo-700">
              {{ $t("digitMemoryTest.results.overallAccuracy") }}
            </div>
          </div>
        </div>

        <div class="space-y-3">
          <div
            class="flex justify-between items-center p-3 bg-slate-50 rounded-lg"
          >
            <span class="text-slate-600">{{
              $t("digitMemoryTest.results.maxLevel")
            }}</span>
            <span class="font-semibold text-slate-800"
              >{{ currentLevel }}-back</span
            >
          </div>
          <div
            class="flex justify-between items-center p-3 bg-slate-50 rounded-lg"
          >
            <span class="text-slate-600">{{
              $t("digitMemoryTest.results.correctTrials")
            }}</span>
            <span class="font-semibold text-slate-800"
              >{{ finalResult.totalCorrect }}/{{
                finalResult.totalTrials
              }}</span
            >
          </div>
          <div
            class="flex justify-between items-center p-3 bg-slate-50 rounded-lg"
          >
            <span class="text-slate-600">{{
              $t("digitMemoryTest.results.nBackCapacity")
            }}</span>
            <span class="font-semibold text-slate-800">{{
              finalResult.workingMemorySpan
            }}</span>
          </div>
        </div>

        <Button
          class="w-full bg-gradient-to-r from-blue-700 to-indigo-600 hover:from-blue-800 hover:to-indigo-700 text-white py-3 text-lg font-semibold shadow-lg hover:shadow-xl transition-all duration-200"
          size="lg"
          @click="handleComplete"
        >
          {{ $t("digitMemoryTest.results.viewDetails") }}
        </Button>
      </CardContent>
    </Card>
  </div>
</template>

<style scoped>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.slide-fade-enter-active {
  transition: all 0.3s ease-out;
}

.slide-fade-leave-active {
  transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-fade-enter-from,
.slide-fade-leave-to {
  transform: translateY(-20px);
  opacity: 0;
}

.step-number {
  @apply w-6 h-6 bg-blue-700 text-white rounded-full flex items-center justify-center text-sm font-semibold flex-shrink-0 mt-0.5;
}

.info-box {
  @apply text-center p-4 bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl border border-blue-200;
}

.info-box-title {
  @apply text-2xl font-bold text-blue-700 mb-1;
}

.info-box-body {
  @apply text-sm text-blue-700;
}

.result-row {
  @apply flex justify-between items-center p-3 bg-slate-50 rounded-lg;
}
</style>
